package com.meme.editor.model.sprite2d;

import java.awt.Graphics2D;
import java.awt.Color;
import java.awt.SystemColor;
import java.util.Vector;

import org.apache.log4j.Logger;

import com.meme.editor.EntityObject;

public class CompositedModule extends Module
{
	static Logger logger = Logger.getLogger (CompositedModule.class);
	
	public CompositedModule ()
	{
		this (null);
	}
	
	public CompositedModule (String name)
	{
		super (name);
	}
	
	//Vector<ModulePart> mChildren;
	
	public ModulePart createNewModulePart ()
	{
		addNewChild ();
		
		return (ModulePart) getChildByIndex (getChildrenCount () - 1);
	}
	
	@Override
	public String getDefaultName ()
	{
		return "Composited";
	}
	
	@Override
	public boolean isValid ()
	{
		for ( int i = 0; i < getChildrenCount (); ++ i)
		{
			if ( ! getChildByIndex (i).isValid() )
				return false;
		}
		
		return true;
	}
	
	@Override
	protected boolean isValidChild (EntityObject entity)
	{
		return entity instanceof ModulePart;
	}
	
	public boolean containsModuleAsPartInSubTree (Module module)
	{
		for (EntityObject entity : getChildren ())
		{
			ModulePart part = (ModulePart) entity;
			Module partModule = part.getModule();
			if ( partModule == module )
				return true;
			else if ( partModule instanceof CompositedModule )
			{
				CompositedModule partCompositedModule = (CompositedModule) partModule;
				if ( partCompositedModule.containsModuleAsPartInSubTree(module) )
					return true;
			}
		}
		
		return false;
	}
	
	@Override
	public EntityObject insertNewChild (int insertPos)
	{
		ModulePart instance = new ModulePart ();
		
		return insertChild (instance, insertPos);
	}
	
	@Override
	public int getMinX ()
	{
		int minX = Integer.MAX_VALUE;
		
		for ( int i = 0; i < getChildrenCount (); ++ i)
		{
			int x = ( (ModulePart) getChildByIndex (i) ).getMinX();
			if ( x < minX )
				minX = x;
		}
		
		return minX;
	}
	
//	@Override
//	public int getMaxX ()
//	{
//		int maxX = Integer.MIN_VALUE;
//		
//		for ( int i = 0; i < getChildrenCount(); ++ i )
//		{
//			int x = ( (ModuleInstance) getChildByIndex (i) ).getMaxX();
//			if ( x > maxX )
//				maxX = x;
//		}
//		
//		return maxX;
//	}
	
	@Override
	public int getMinY ()
	{
		int minY = Integer.MAX_VALUE;
		
		for ( int i = 0; i < getChildrenCount (); ++ i)
		{
			int y = ( (ModulePart) getChildByIndex (i) ).getMinY();
			if ( y < minY )
				minY = y;
		}
		
		return minY;
	}
	
//	@Override
//	public int getMaxY ()
//	{
//		int maxY = Integer.MIN_VALUE;
//		
//		for ( int i = 0; i < getChildrenCount(); ++ i )
//		{
//			int y = ( (ModuleInstance) getChildByIndex (i) ).getMaxY();
//			if ( y > maxY )
//				maxY = y;
//		}
//		
//		return maxY;
//	}
	
	@Override
	public int getWidth ()
	{
		if ( getChildrenCount () == 0 )
			return 0;
		
		int minX = Integer.MAX_VALUE;
		int maxX = Integer.MIN_VALUE;
		
		for ( int i = 0; i < getChildrenCount (); ++ i)
		{
			int x = ( (ModulePart) getChildByIndex (i) ).getMinX();
			if ( x < minX )
				minX = x;
			
			x += ( (ModulePart) getChildByIndex (i) ).getWidth();
			if ( x > maxX )
				maxX = x;
		}
		
		return maxX - minX;
	}
	
	@Override
	public int getHeight ()
	{
		if ( getChildrenCount () == 0 )
			return 0;
		
		int minY = Integer.MAX_VALUE;
		int maxY = Integer.MIN_VALUE;
		
		for ( int i = 0; i < getChildrenCount (); ++ i)
		{
			int y = ( (ModulePart) getChildByIndex (i) ).getMinY();
			if ( y < minY )
				minY = y;
			
			y += ( (ModulePart) getChildByIndex (i) ).getHeight();
			if ( y > maxY )
				maxY = y;
		}
		
		return maxY - minY;
	}
	
	@Override
	public boolean isImageHybird ()
	{
		for ( int i = 0; i < getChildrenCount (); ++ i)
		{
			ModulePart mi = (ModulePart) getChildByIndex (i);
			if ( mi.isImageHybird () )
				return true;
		}
		
		return false;
	}

	@Override
	public boolean isPaletteHybird ()
	{
		for ( int i = 0; i < getChildrenCount (); ++ i)
		{
			ModulePart mi = (ModulePart) getChildByIndex (i);
			if ( mi.isImageHybird () || mi.isPaletteHybird () )
				return true;
		}
		
		return false;
	}
	
	@Override
	public void render (Graphics2D g, int posX, int posY, boolean flipX, boolean flipY, int scale, int flags)
	{
		for ( int i = 0; i < getChildrenCount (); ++ i)
		{
			ModulePart mi = (ModulePart) getChildByIndex (i);
			mi.render(g, posX, posY, flipX, flipY, scale, flags);
		}
	}
	
	
	// special for animated module
	
	public void render (Graphics2D g, int posX, int posY, int scale)
	{
		render (g, posX, posY, false, false, scale, 0);
	}
	
	public void render (Graphics2D g, int posX, int posY, int scale, ModulePart selectedPart)
	{
		logger.assertLog (selectedPart == null || selectedPart.getParent() == this, "error, where?");
			
		for ( int i = 0; i < getChildrenCount (); ++ i)
		{
			ModulePart mi = (ModulePart) getChildByIndex (i);
	
			mi.render(g, posX, posY, false, false, scale, 0);
			
			// draw mask in selected part
			if (mi == selectedPart)
			{
				int x = posX + mi.getMinX() * scale;
				int y = posY + mi.getMinY() * scale;
				int width = mi.getWidth() * scale;
				int height = mi.getHeight() * scale;
				
				Color oldcolor = g.getColor();
				g.setColor( new Color(0x7f0000ff, true) );
				g.fillRect(x, y, width, height);
				g.setColor(oldcolor);
			}
		}
		
		// draw origin of selected instance
		if ( selectedPart != null)
		{
			
		}
	}
	
	public ModulePart getChildAtPos (int x, int y, int fromIndex)
	{
		int childcount = getChildrenCount ();
		int index = fromIndex;
		int k = childcount;
		while (-- k >= 0)
		{
			-- index;
			if ( index < 0 )
				index += childcount;
			
			index = index % childcount;

			ModulePart mi = (ModulePart) getChildByIndex (index);
			int left = mi.getMinX();
			int right = left + mi.getWidth();
			int top = mi.getMinY();
			int bottom = top + mi.getHeight();
			if ( left <= x && x < right && top <= y && y < bottom )
				return mi;
		}
		
		return null;
	}

}
